home *** CD-ROM | disk | FTP | other *** search
/ Collection of Tools & Utilities / Collection of Tools and Utilities.iso / print / uplabel.zip / GETARG.C < prev    next >
C/C++ Source or Header  |  1990-12-19  |  4KB  |  183 lines

  1. /*
  2. getarg.c
  3. Written by D'Arcy J.M. Cain
  4. D'Arcy Cain Consulting
  5. 275 Manse Road, Unit # 24
  6. West Hill, Ontario
  7. M1E 4X8
  8. 416 281 6094
  9.  
  10. UUCP: darcy@druid
  11.  
  12. This routine may be freely distributed as long as credit is given to D'Arcy
  13. J.M. Cain, the source is included and this notice remains intact.  There is
  14. specifically no restrictions on use of the program including personal or
  15. commercial.  You may even charge others for this routine as long as the above
  16. conditions are met.
  17.  
  18. This is not shareware and no registration fee is expected.  If you like the
  19. program and want to support this method of distribution, write a program or
  20. routine and distribute it the same way and I will feel I have been paid.
  21.  
  22. Of course gifts of money, drinks and extravagant jewels are always welcome.
  23. */
  24.  
  25. #ifdef BSD
  26. #include <strings.h>
  27. #else
  28. #include <string.h>
  29. #define    index    strchr
  30. #endif
  31.  
  32. #include    <stdlib.h>
  33. #include    <malloc.h>
  34. #include    <ctype.h>
  35.  
  36. #ifndef        NULL
  37. #define        NULL    (void *)(0)
  38. #endif
  39.  
  40. int        optind = 0;
  41. char    *optarg;
  42.  
  43. /* Note that the above declarations can cause problems with programs
  44. that use getopt(3) if this module is scanned first in the link phase.
  45. This means that if you use getopt sometimes then you should keep this
  46. module separate and link it in specifically when needed.  Alternatively
  47. you can change the names of the above externs (perhaps declare optind as
  48. static as programs don't really need it anyway) and have a #define so
  49. that the program still uses the above name(s).  I considered using a
  50. different name for optarg but was afraid that anything I picked would
  51. conflict with user's names.
  52. */
  53.  
  54. static char        **pargv = NULL;
  55. static int        pargc = 0;
  56.  
  57. int        initarg(int argc, char **argv)
  58. {
  59.     int        k = argc * sizeof(char *);
  60.  
  61.     /* check for trivial case */
  62.     if (!argc)
  63.         return(0);
  64.  
  65.     /* get or expand space */
  66.     if (pargc == 0)
  67.         pargv = malloc(k);
  68.     else
  69.         pargv = realloc(pargv, pargc + k);
  70.  
  71.     if (pargv == NULL)
  72.         return(-1);                /* not enough memory for argument pointers */
  73.  
  74.     /* if adding arguments insert them at current argument */
  75.     if (pargc)
  76.         for (k = pargc - 1; k >= optind; k--)
  77.             pargv[k + argc] = pargv[k];
  78.  
  79.     for (k = 0; k < argc; k++)
  80.         pargv[optind + k] = argv[k];
  81.  
  82.     pargc += argc;
  83.     return(pargc);
  84. }
  85.  
  86. /*
  87. The meat of the module.  This returns options and arguments similar to
  88. getopt() as described above.
  89. */
  90.  
  91. int        getarg(const char *opts)
  92. {
  93.     static int sp = 0, end_of_options = 0;
  94.     int c;
  95.     char *cp;
  96.  
  97.     optarg = NULL;
  98.  
  99.     /* return 0 if we have read all the arguments */
  100.     if(optind >= pargc)
  101.     {
  102.         if (pargv != NULL)
  103.             free(pargv);
  104.  
  105.         pargv = NULL;
  106.         pargc = 0;
  107.         optind = 0;
  108.         return(0);
  109.     }
  110.  
  111.     /* Are we starting to look at a new argument? */
  112.     if(sp == 0)
  113.     {
  114.         /* return it if it is a file name */
  115.         if ((*pargv[optind] != '-') || end_of_options)
  116.         {
  117.             optarg = pargv[optind++];
  118.             return(-1);
  119.         }
  120.  
  121.         /* special return for standard input */
  122.         if (strcmp(pargv[optind], "-") == 0)
  123.         {
  124.             optind++;
  125.             return('-');
  126.         }
  127.  
  128.         /* "--" signals end of options */
  129.         if (strcmp(pargv[optind], "--") == 0)
  130.         {
  131.             end_of_options = 1;
  132.             optind++;
  133.             return(getarg(opts));
  134.         }
  135.  
  136.         /* otherwise point to option letter */
  137.         sp = 1;
  138.     }
  139.     else if (pargv[optind][++sp] == 0)
  140.     {
  141.         /* recursive call if end of this argument */
  142.         sp = 0;
  143.         optind++;
  144.         return(getarg(opts));
  145.     }
  146.  
  147.     c = pargv[optind][sp];
  148.  
  149.     if(c == ':' || (cp = index(opts, c)) == NULL)
  150.         return('?');
  151.  
  152.     if(*++cp == ':')
  153.     {
  154.         /* Note the following code does not allow leading
  155.            spaces or all spaces in an argument */
  156.  
  157.         while (isspace(pargv[optind][++sp]))
  158.             ;
  159.  
  160.         if(pargv[optind][sp])
  161.             optarg = pargv[optind++] + sp;
  162.         else if(++optind >= pargc)
  163.             c = '?';
  164.         else
  165.             optarg = pargv[optind++];
  166.  
  167.         sp = 0;
  168.     }
  169.     else if (*cp == ';')
  170.     {
  171.         while (isspace(pargv[optind][++sp]))
  172.             ;
  173.  
  174.         if (pargv[optind][sp])
  175.             optarg = pargv[optind] + sp;
  176.  
  177.         optind++;
  178.         sp = 0;
  179.     }
  180.  
  181.     return(c);
  182. }
  183.